home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / CLESSONS.ZIP / LESSON11 < prev    next >
Text File  |  1986-04-04  |  23KB  |  517 lines

  1. .NT
  2.  A NOTE ABOUT THE LESSONS in C 
  3. .b4-24R5C4
  4. These were written while the author was ~Ilearning~N  the language and since
  5. .R6C4
  6. they  are  ~Ifree~N ( to  copy  and/or  distribute ) there  is  a money-back
  7. .R7C4
  8. guarantee on the accuracy of each and every statement in the lessons (!)
  9. .R9C4
  10. The  ~Idisplay~N  program was written ( in C ) in order to provide a vehicle
  11. .R10C4
  12. for displaying the lessons.
  13. .R12C5
  14. .B
  15. P.J.Ponzo
  16. .B
  17. Dept. of Applied Math
  18. .B
  19. Univ. of Waterloo
  20. .B
  21. Ontario N2L 3G1
  22. .K16,32
  23. PonzoTUTOR
  24. .WNT
  25.     a little STRUCTURE   
  26. .R5C1
  27.     If we wish to keep a record of, say, friends ... including name,
  28.     address, birthdate, etc. we might declare:
  29.  
  30. ~b~Ichar name[20], address[40], birthdate[15];~N
  31.  
  32.     where ~b~Iname~N, for example, is an array of 20 characters which is meant to
  33.     hold the name of one such friend, and ~b~Iaddress~N holds 40 ~b~Ichar~Ns, etc.
  34.     If we want 100 such records, we could use:    
  35.  
  36. ~b~Ichar name[100][20], address[100][40], birthdate[100][15];~N
  37.  
  38.     where name[0], name[1],name[2], etc. are each arrays of 20 characters, etc.
  39.  
  40.     We would print our list via a statement like:
  41.  
  42. ~b~Ifor (i=0; i<100; i++) printf("\n%s %s %s",name[i],address[i],birthdate[i]);~N
  43. .WN
  44.     Since the ~b~Ibirthdate~N has the form "Nov 6, 1934" (for example) we would
  45.     need to extract the last number ( 1934), and perform a subtraction, in 
  46.     order to determine his (her?) age ... and would need all such numbers in
  47.     order to deduce the average age of our friends. So we might declare
  48.     ~b~Ibirthdate~N to be a trio of objects: an array of characters (to hold
  49.     the birth-month, like "Nov"), an integer (to hold the birth-day) and a
  50.     second integer (to hold the birth-year) ... that way we could perform some
  51.     arithmetic on the integer parts of the ~b~Ibirthdate~N.
  52.  
  53. ~b~Ichar name[100][~V20~N~b~I], address[100][~V40~N~b~I];    ~N
  54. ~b~Ichar birth_month[100][~V4~N~b~I];                ~N
  55. ~b~Iint  birth_day[100], birth_year[100];    ~N
  56.  
  57.     The above would do it. Sufficiently many arrays (of characters and 
  58.     integers) for 100 friends, each with names of ~V 19 ~N characters (or less)
  59.     and addresses of ~V 39 ~N characters (or less) and ~V 3 ~N characters for 
  60.     the birth_month (we'll need the terminating '\0' in each char array!)
  61.     ... and 100 birth_days and birth_years (remember that birth_day[0] to 
  62.     birth_day[99] is 100 birth-days!) 
  63. .w
  64.  
  65.     It would be nice to have a DATA TYPE which held ~Ione~N such record, with
  66.     name, address, etc. and mixed ~b~Ichar~Ns and ~b~Iint~Ns !!
  67. .WK8,60
  68.   amen!
  69. .WN
  70. .R2C1B
  71.     ... let's welcome the STRUCTURE ...
  72. .R6C1
  73.     We invent a ~Istructure~N called ~b~Idate~N which includes a ~V3~N character 
  74.     ~b~Imonth~N ( hence month[~V4~N] ) and two ~b~Iint~Ns (day and year).
  75.  
  76.     We are accustomed to saying ~b~Iint x;~N and ~b~Ichar y;~N, meaning that
  77.     ~b~Ix~N is of DATA TYPE ~b~Iint~N and ~b~Iy~N is of DATA TYPE ~b~Ichar~N.
  78.     SO, we will want to say ~b~Idate birth;~N meaning that ~b~Ibirth~N is
  79.     of DATA TYPE ~b~Idate~N meaning a collection of objects: 
  80.     a ~b~Ichar month[4]~N, an ~b~Iint day~N and an ~b~Iint year~N.
  81.  
  82.     But, if ~b~Idate~N is a ~b~Istruc~Nture (with the elements mentioned above)
  83.     then we will refer to it as ~b~Istruct date~N, to inform the compiler that 
  84.     ~b~Idate~N is no ordinary guy but is, in fact, a ~b~Istruct~N ...
  85.     with all the rights and privileges thereto appertaining!
  86.  
  87.  
  88.     ~ISO~N, we declare ~b~Ibirth~N to be such a structure (called ~b~Idate~N) via:
  89.  
  90. ~b~Istruct date birth;~N          see? ~Vstruct date~N go together!
  91. .WK8,32
  92. confusing!
  93. .WN
  94.     So why wouldn't we just define a ~b~Istruct~Nure called ~b~Ibirth~N, which
  95.     has the 3 members: ~b~Imonth[4]~N and ~b~Iint day~N and ~b~Iint year~N ??
  96.  
  97.     Because we will want to use this ~b~Istruc~N for ~Iother~N ~b~Idate~Ns, like:
  98.  
  99. ~b~Istruct date death;~N
  100.  
  101.     Too morbid?  Then how about:
  102.  
  103. ~b~Istruct date WhenWeMet;~N
  104.  
  105.     Now, ~b~IWhenWeMet~N is of DATA TYPE ~b~Idate~N too, containing the same
  106.     3 elements of ~b~Ichar month[4]~N and ~b~Iint day~N and ~b~Iint year~N !!
  107.  
  108.     (Note: some compilers may not recognize names like ~b~IWhenWeMet~N
  109.            but may restrict names to, say, ~I8~N characters or less).
  110. .WK19,32
  111.   go on!
  112. .WNT
  113.     inside a STRUCTure    
  114. .R5C1
  115.     Before we see how to define such a ~b~Istruct~Nure as ~b~Idate~N, we use it!
  116.     It will have ~I3~N members: ~b~Imonth~N, ~b~Iday~N, ~b~Iyear~N.
  117.     We declare:
  118.  
  119. ~b~Istruct date birth[100], WhenWeMet[100];~N
  120.  
  121.     so each of ~b~Ibirth[0]~N, ~b~Ibirth[1]~N, etc. and ~b~IWhenWeMet[0]~N, ~b~IWhenWeMet[1]~N, etc.
  122.     are ~b~Istruct~Ns of TYPE ~b~Idate~N.
  123.     We refer to ~b~Ibirth[i]~F.~N~b~Imonth~N, ~b~Ibirth[i]~F.~N~b~Iday~N and ~b~Ibirth[i]~F.~N~b~Iyear~N and to
  124.     ~b~IWhenWeMet[i]~F.~N~b~Imonth~N, ~b~IWhenWeMet[i]~F.~N~b~Iday~N and ~b~IWhenWeMet[i]~F.~N~b~Iyear~N 
  125.     for i=0, 1, 2, ... up to the number of friends we have ( and each
  126.     reflects the ~I3~N members ~b~Imonth~N, ~b~Iday~N and ~b~Iyear~N of the
  127.     ~b~Idate~N structure ... OK?)
  128. .K18,32
  129. note the .
  130. .WN
  131.     To input all this information we might use:
  132. .R4C1
  133. ~b~Iprintf("\n How many friends do you have "); scanf("%s",&number);     ~N
  134. ~b~Ifor (i=0; i<number; i++) {                                           ~N
  135. ~b~I    printf("\n For friend %d",i);                                    ~N
  136. ~b~I    printf("\n Enter Month of Birth "); scanf("%s",&birth[i].month); ~N
  137. ~b~I    printf("\n Enter Day   of Birth "); scanf("%s",&birth[i].day);   ~N
  138. ~b~I    printf("\n Enter Year  of Birth "); scanf("%s",&birth[i].year);  ~N
  139. ~b~I}                                                                    ~N
  140. .s
  141. .R4C1
  142. ~Vprintf("\n How many friends do you have "); scanf("%s",&number);  ~N
  143. .r
  144.     Here we ask for the number of friends, and store it in ~b~Inumber~N
  145.     (note the ~V&~Nnumber!)
  146. .WR4C1
  147. ~b~Iprintf("\n How many friends do you have "); scanf("%s",&number);  ~N
  148. ~Vfor (i=0; i<number; i++) {                                        ~N
  149. .r
  150.     Then, we go through each of ~b~Inumber~N of friends, asking questions:
  151. .WR5C1
  152. ~b~Ifor (i=0; i<number; i++) {                                        ~N
  153. ~V    printf("\n For friend %d:",i+1);                              ~N
  154. .r
  155.     We remind the user which friend we're working on by ~b~Iprintf~Ning ...   
  156.     ~r~I For friend 1:~N  then ~r~I For friend 2:~N  etc.
  157.     (We don't refer to "friend 0:" ... that would be insulting ...so we print
  158.     the numbers ~b~Ii+1~N rather than ~b~Ii~N).
  159. .WR6C1
  160. ~b~I    printf("\n For friend %d",i);                                 ~N
  161. ~V    printf("\n Enter Month of Birth "); scanf("%s",&birth[i].month); ~N
  162. .r
  163.     We ask ~r~I Enter Month of Birth ~N and put the answer into ~V&birth[i].month~N
  164.     (for the ~Ii~Nth friend) and, as required by ~b~Iscanf()~N,
  165.     we use the ~I&ddress~N !
  166. .WR7C1
  167. ~b~I    printf("\n Enter Month of Birth "); scanf("%s",&birth[i].month); ~N
  168. ~V    printf("\n Enter Day   of Birth "); scanf("%s",&birth[i].day);   ~N
  169. ~V    printf("\n Enter Year  of Birth "); scanf("%s",&birth[i].year);  ~N
  170. .r
  171.     ... and so on, for the ~b~Ibirth.day~N and ~b~Ibirth.year~N               
  172. .WN
  173.     ... unfortunately, this won't (quite) work ... did you see why?
  174. .WR2C1
  175.     We'll repeat the program excerpt:
  176. ~b~Iprintf("\n How many friends do you have "); scanf("%~Fs~N~b~I",&number);     ~N
  177. ~b~Ifor (i=0; i<number; i++) {                                           ~N
  178. ~b~I    printf("\n For friend %d",i);                                    ~N
  179. ~b~I    printf("\n Enter Month of Birth "); scanf("%s",&birth[i].month); ~N
  180. ~b~I    printf("\n Enter Day   of Birth "); scanf("%~Fs~N~b~I",&birth[i].day);   ~N
  181. ~b~I    printf("\n Enter Year  of Birth "); scanf("%~Fs~N~b~I",&birth[i].year);  ~N
  182. ~b~I}                                                                    ~N
  183.     ~b~Inumber~N     should have a ~b~I%d~N (for an integer)
  184.     ~b~Ibirth[i].day~N  should have a ~b~I%d~N (for an integer)
  185.     ~b~Ibirth[i].year~N should have a ~b~I%d~N (for an integer)
  186.     ... but there's something else ...
  187. .sWR6C1
  188. ~V    printf("\n Enter Month of Birth "); scanf("%s",&birth[i].month); ~N
  189. .r
  190.     ~b~Iscanf()~N will put the ~I3~N characters typed at the keyboard, say "Nov",
  191.     into the memory reserved for ~b~Ibirth[i].month~N, but won't put in a ~I'\0'~N!
  192.  
  193.     WE must put it in ( ... while we're praying that the user doesn't type
  194.     november, which is much too long to fit into the ~I4~N bytes we've reserved
  195.     for the month!)
  196. .WN
  197.     We could initialize all the bytes in the ~b~Ibirth.month~N to ~I'\0'~N via:
  198. ~b~Ifor (i=0; i<100; i++)    {      /* for all 100 friends  */~N
  199. ~b~I    for (j=0; j<4; j++)  {      /* for each of 4 bytes  */~N
  200. ~b~I        birth[i].month+j='\0';  /* set byte to '\0'     */~N
  201. ~b~I    }                           /* end of inner "for"   */~N
  202. ~b~I}                               /* end of outer "for"   */~N
  203.  
  204.     ... then (provided the user doesn't type more than a ~I3~N character month!)
  205.     we've got all the ~I'\0' string terminators~N we'll need.
  206.  
  207.     This little ritual is necessary because ~b~Iscanf()~N is meant as a
  208.     general-purpose input ... ~b~Iint~Ns and ~b~Ifloats~N and ~b~Ichar~Ns etc.
  209.  
  210.     A special-purpose input ... just for ~Istrings~N of ~b~Ichar~Ns ... would
  211.     be smart enough to append the ~I'\0'~N (wouldn't it?)
  212.  
  213.     The ~Istdio.h~N library of C-functions will contain such a function.
  214.     ~b~Igets(&sam)~N will ~b~Iget~N a ~b~Is~Ntring and put it into the
  215.     address ~b~I&sam~N. Just like scanf() requires a ~r~Ipointer~N to the memory
  216.     location where the input is to be stored, so does gets().
  217. .WN
  218.     We write:
  219. 1 ~b~Iprintf("\n How many friends do you have "); scanf("%d",&number);     ~N
  220. 2 ~b~Ifor (i=0; i<number; i++) {                                           ~N
  221. 3 ~b~I    printf("\n For friend %d",i);                                    ~N
  222. 4 ~b~I    printf("\n Enter Month of Birth "); gets(&birth[i].month);       ~N
  223. 5 ~b~I    printf("\n Enter Day   of Birth "); scanf("%d",&birth[i].day);   ~N
  224. 6 ~b~I    printf("\n Enter Year  of Birth "); scanf("%d",&birth[i].year);  ~N
  225. 7 ~b~I}                                                                    ~N
  226.     and the ~b~Igets()~N in line 4 will collect each ~b~Ichar~Naracter typed,
  227.     and when a ~I\n~Newline is typed (the Return or Enter key) it will exchange
  228.     it for a ~I'\0'~N ... and put everything into the memory location indicated.
  229. .K16,32
  230. wunderbar!
  231. .WNT
  232.     defining a STRUCTure    
  233. .R5C1
  234.     It's about time we ~Idefined~N our ~b~Istruct date~N :
  235. ~b~I     struct date   {       ~N
  236. ~b~I          char month[4];   ~N
  237. ~b~I          int day;         ~N
  238. ~b~I          int year;        ~N
  239. ~b~I    };                     ~N
  240.     Note the structure of a structure:
  241. ~b~I     struct ~Vname~N~b~I   ~F{~N~b~I       ~N
  242. ~b~I          --- all the ---  ~N
  243. ~b~I          --- members ---  ~N
  244. ~b~I          --- go here ---  ~N
  245. ~b~I    ~F}~N~V;~N~b~I                     ~N
  246.  
  247.     We give it a ~Vname~N (like ~b~Idate~N) so we can declare other objects to
  248.     be of this DATA TYPE ( remember ~b~Ibirth~N and ~b~IWhenWeMet~N ? )
  249.     ... and an opening and closing ~F~b~I{~N and ~F~b~I}~N
  250.     ... and the various members (like ~b~Ichar month[4]~N, etc.)
  251.     ... and a final ~V ; ~N
  252. .WK6,60
  253. final ; ??
  254. .WN
  255. ~b~I     struct date   {             ~N
  256. ~b~I          char month[4];         ~N
  257. ~b~I          int day;               ~N
  258. ~b~I          int year;              ~N
  259. ~b~I    }~F;~N~b~I                           ~N
  260.  
  261.     This final ~F;~N is meaningful!
  262.  
  263.     Because a ~b~Istruct date~N is to be used just like ~b~Iint~N or ~b~Ichar~N,
  264.     and because we usually say ~b~Iint x~F;~N or ~b~Ichar x~F;~N (with a final ~F;~N),
  265.     then we terminate a structure definition with a ~F;~N and expect to be able
  266.     to say ~b~Istruct date {   ~N
  267.            ~b~I   --- etc ---  ~N
  268.            ~b~I} x~F;~N~b~I            ~N  (note the similarity with ~b~Iint x;~N etc.)
  269.  
  270. .w
  271.     SO, for our earlier example, we could say:
  272.  
  273. ~b~I     struct date   {             ~N
  274. ~b~I          char month[4];         ~N
  275. ~b~I          int day;               ~N
  276. ~b~I          int year;              ~N
  277. ~b~I    } birth[100],WhenWeMet[100]~F;~N~b~I ~N
  278.     ... and we've defined our ~b~Istruct date~N AND declared ~b~Ibirth[]~N 
  279.     and ~b~IWhenWeMet[]~N to be such structures ... all at once!
  280. .K2,60
  281. how nice!
  282. .WN
  283.     Now let's return to the record of our "friends", which includes ~b~Iname~N
  284.     and ~b~Iaddress~N as well as some ~b~Idates~N.
  285.  
  286.     For each "record" we will define ~Ianother~N structure ... let's call it
  287.     "record" (what else?)
  288. ~b~I     struct  record  {             ~N
  289. ~b~I          char name[20];           ~N
  290. ~b~I          char address[40];        ~N
  291. ~b~I          struc date birth;        ~N
  292. ~b~I          struc date WhenWeMet;    ~N
  293. ~b~I     } friend[100];                ~N
  294.  
  295.     Note that we've not only defined the ~b~Istruct~N called ~b~Irecord~N but we've
  296.     also declared 100 such structures, using the "final" ~b~Ifriend[100];~N
  297.  
  298.     ~b~Ifriend[0]~N and ~b~Ifriend[1]~N and ~b~Ifriend[2]~N etc. are ALL of type
  299.     ~b~Irecord~N hence contain members ~b~Iname~N, ~b~Iaddress~N, ~b~Ibirth~N
  300.     and  ~b~IWhenWeMet~N.
  301.  
  302. .w
  303.     The first two (~b~Iname~N and ~b~Iaddress~N) are ~b~Ichar~Nacter arrays
  304.     ~IBUT~N the last two (~b~Ibirth~N and ~b~IWhenWeMet~N) are ... SURPRISE (!)
  305.     ~Istructures~N of TYPE ~b~Idate~N !!!
  306. .WN
  307.     We now have two structures defined:
  308. ~b~I  struct date   {           ~N     ~b~I  struct  record  {             ~N
  309. ~b~I       char month[4];       ~N     ~b~I       char name[20];           ~N
  310. ~b~I       int day;             ~N     ~b~I       char address[40];        ~N
  311. ~b~I       int year;            ~N     ~b~I       struc date birth;        ~N
  312. ~b~I  };                        ~N     ~b~I       struc date WhenWeMet;    ~N
  313.                                  ~b~I} friend[100];                  ~N
  314.  
  315.     Earlier we declared 200 structures of TYPE ~b~Idate~N (namely ~b~Ibirth[100]~N
  316.     and ~b~IWhenWeMet[100]~N). We also referred to the ~I3~N members of ~b~Ibirth[47]~N
  317.     (for example) as ~b~Ibirth[47]~F.~N~b~Imonth~N, ~b~Ibirth[47]~F.~N~b~Iday~N and ~b~Ibirth[47]~F.~N~b~Iyear~N.
  318.  
  319.     Now we won't need to define these 200 structures (sorry about that!) since
  320.     ~b~Istruct date birth~N and ~b~Istruct date WhenWeMet~N are embedded in the
  321.     ~b~Irecord~N structure ... ~Istructures within structures~N!!
  322. .K16,32
  323. aw c'mon!!
  324. .WNT
  325.     STRUCTures within STRUCTures ??   
  326. .R10C1
  327.                        ~V  NOBODY SAID THIS WAS EASY!  ~N
  328. .b8-12
  329. .K16,32
  330. !@#$%^&*?!
  331. .WN
  332. ~b~I  struct date   {           ~N     ~b~I  struct  record  {             ~N
  333. ~b~I       char month[4];       ~N     ~b~I       char name[20];           ~N
  334. ~b~I       int day;             ~N     ~b~I       char address[40];        ~N
  335. ~b~I       int year;            ~N     ~b~I       struc date birth;        ~N
  336. ~b~I  };                        ~N     ~b~I       struc date WhenWeMet;    ~N
  337.                                  ~b~I} friend[100];                  ~N
  338.     To input (for example) the name of the friend[47], we'd say:
  339.  
  340. ~b~Iprintf("\n Name please : "); gets(&friend[47].name);~N
  341.  
  342.     ... and ... to input his (her?) birth.month we'd say:
  343.  
  344. ~b~Iprintf("\n Month of Birth : "); gets(&friend[47].birth.month);~N
  345.  
  346.     Note the use of ~b~Igets()~N ( to automatically append the ~I'\0'~N ).
  347.     Note, too, the very logical way we refer to the member of a structure
  348.     within a structure ... ~b~Ifriend[47].birth.month~N
  349. .K19,60
  350. gorgeous!!
  351. .WN
  352. ~b~Imain()   {                    /* not-too-useful-program */               ~N
  353. ~b~I    int number, i;                                                       ~N
  354. ~b~I    struct date  {                                                       ~N
  355. ~b~I         char month[4];                                                  ~N
  356. ~b~I         int day;                                                        ~N
  357. ~b~I         int year;                                                       ~N
  358. ~b~I    };                                                                   ~N
  359. ~b~I    struct record {                                                      ~N
  360. ~b~I         char name[20];                                                  ~N
  361. ~b~I         char address[40];                                               ~N
  362. ~b~I         struct date birth;                                              ~N
  363. ~b~I    } friend[100];                                                       ~N
  364. ~b~I    printf("\nHow many friends : "); scanf("%d",&number);                ~N
  365. .w                                                                           ~N
  366. ~b~I    for (i=0; i<number; i++) {                                           ~N
  367. ~b~I        printf("\n For friend %d",i+1);                                  ~N
  368. ~b~I        printf("\nName ? ");           gets(&friend[i].name);            ~N
  369. ~b~I        printf("\nAddress ? ");        gets(&friend[i].address);         ~N
  370. ~b~I        printf("\nMonth of birth ? "); gets(&friend[i].birth.month);     ~N
  371. ~b~I        printf("\nDay of birth ? ");   scanf("%d",&friend[i].birth.day); ~N
  372. ~b~I        printf("\nYear of birth ? ");  scanf("%d",&friend[i].birth.year);~N
  373. ~b~I    }                                                                    ~N
  374. .WN
  375. ~b~I    printf("\nSUMMARY of your %d friends",number);                      ~N
  376. ~b~I    for (i=0; i<number; i++) {                                          ~N
  377. ~b~I        printf("\nName:%s",friend[i].name);                             ~N
  378. ~b~I        printf("\nAddress:%s",friend[i].address);                       ~N
  379. ~b~I        printf("\nBorn on %s %d,%d",                                    ~N
  380. ~b~I        friend[i].birth.month,friend[i].birth.day,friend[i].birth.year);~N
  381. ~b~I    }                                                                   ~N
  382. ~b~I}                                                                       ~N
  383.     giving a (typical) printout:
  384. ~r~IName:Peter Ponzo~N
  385. ~r~IAddress:49 Margaret S., Waterloo, Ont.~N
  386. ~r~IBorn on Nov 6,1934~N
  387. .K16,32
  388. a-a-a-ah!
  389. .WNT
  390.     and POINTERS to STRUCTURES!    
  391. .R4C1
  392.     One sometimes feels frustrated in writing an elaborate function which does
  393.     the most wonderful things, only to get from such a function  a single
  394.     ~b~Iint~N or ~b~Ifloat~N or ~b~Ichar~N ( you can't ~b~Ireturn(a,b,c,d,e)~N
  395.     at the end of the function, but only ~b~Ireturn(a)~N !@#$% ).
  396.  
  397.     BUT, the function can create an elaborate ~Istructure~N which houses all the
  398.     wonderful things, then ~b~Ireturn(a)~N where ~n~Ia~N is a ~r~Ipointer~N to
  399.     the structure!
  400.  
  401.     In fact we've used such a function ... one which returns a ~r~Ipointer~N.
  402.     Before I tell you which function it is (from the ~Istdio.h~N library), let's
  403.     see how such a function should be declared.
  404.  
  405.     Consider
  406. ~b~Ichar f();~N  which declares ~b~If()~N to be a function which returns a ~b~Ichar~N
  407.     Then, to declare a function which returns a ~r~Ipointer~N 
  408.     to a ~b~Ichar~N it would be sensible to use the format:
  409. ~b~Ichar *f();~N   ... right?
  410. .WK19,60
  411.   RIGHT!
  412. .WN
  413.     ~ISO~N ... if the function ~b~If()~N were to return a ~r~Ipointer~N to a
  414.     structure called ~b~Isam~N, we'd declare it with:
  415.  
  416. ~b~Isam *f();~N    ... right?
  417. .WK16,32
  418.   RIGHT!
  419.  
  420.     And what if ~b~Isam~N was ~b~Itypedef~Nined to be a structure, as in:
  421.  
  422. ~b~Itypedef SomeStructure  SAM;~N      ( where we have agreed to use capitals )
  423.  
  424.     Then the function ~b~If()~N would be declared:
  425.  
  426. ~b~ISAM *f();~N    ... right?
  427. .WK16,32
  428.           
  429. .K16,32
  430.   RIGHT!!
  431. .WN
  432.  
  433.  
  434.     ~INOW~N ... remember when we used:
  435.  
  436. ~b~IFILE *fopen();~N     ???
  437.  
  438.     In fact, when we ~b~Ifopen()~N a file on a disk, the operating system
  439.     returns a ~r~Ipointer~N to a ~Istructure~N ( called ~b~IFILE~N ) and this
  440.     structure contains all the wonderful things we need to know about the
  441.     file ... and that's why we also declare this ~r~Ipointer~N ~b~Ifp~N:
  442.  
  443. ~b~IFILE *fp, *fopen();~N
  444.  
  445.     and say (subsequent to the above declaration):
  446.  
  447. ~b~I     fp=fopen();~N       so we assign to ~b~Ifp~N the ~r~Ipointer~N returned
  448.                              by ~b~Ifopen()~N.
  449.  
  450.     Then, when we want to get a character from this file, we need only pass to
  451.     ~b~Igetc()~N this ~r~Ipointer~N ( as in ~b~Igetc(fp)~N ) and now the ~b~Igetc()~N
  452.     function will be able to extract all the wonderful things it needs ...
  453.     ~Ifrom the structure~N!
  454. .WK1,60
  455. magnifico!
  456. .WN
  457.  
  458.     ~INOW~N, if ~b~Isam *f();~N is the way we ~Ideclare f() to be a function~N
  459.     which returns a ~r~Ipointer~N to an object of TYPE ~b~Isam~N (which could
  460.     be an ~b~Iint~N or a ~b~Ifloat~N or a ~b~Istruct~N etc.), then how should
  461.     we ~Ideclare f to be a pointer~N to a function which returns an object
  462.     of TYPE ~b~Isam~N ????
  463. .K19,60
  464. I give up!
  465. .W
  466.  
  467. ~b~Isam  (*f)();~N      
  468.  
  469.     says that ~b~If~N is now the ~r~Ipointer~N ... because we used ~b~I(*f)~N ...
  470.     and the thing it points to is ~b~I*f~N ( remember that ~b~Iint *x;~N declares
  471.     ~b~Ix~N to be a ~r~Ipointer~N to an ~b~Iint~N, and the ~b~Iint~N is ~b~I*x~N )
  472.     ~ISO~N, since ~b~I(*f)~N is to be a ~Ifunction~N, we say ~b~I(*f)()~N !
  473.  
  474.     ... and we've seen ~Ithis~N curious notation before too!
  475. .WK19,60
  476.    amen!
  477. .WN
  478.     Suppose that ~b~Iptr~N is a ~r~Ipointer~N to a ~Istruct~Nure 
  479.    ( declared using ~b~I*ptr~N so that ~b~I(*ptr)~N ~IIS~N the structure itself ).
  480.     Suppose the structure had a member called ~b~Iname~N. 
  481.     Then we'd refer to this member as:  ~b~I(*ptr).name~N
  482.     ( as in ~b~I(*ptr).name="George";~N )
  483.  
  484.     Another (simpler) notation ~Ifor the same thing~N is:
  485.  
  486.     ~b~Iptr -> name~N  (use this only if ~b~Iptr~N is a ~r~Ipointer~N)
  487.  
  488.     ... and if the structure had a member ~b~Ibirth~N which was itself a structure
  489.     containing a member called ~b~Imonth~N, then we can use the notation:
  490.  
  491.     ~b~Iptr->birth.month~N  ( which means ~b~I(*ptr).birth.month~N )
  492.  
  493.     as in ~b~Iptr->birth.month="May";~N                        
  494.  
  495.     ~IAND~N, if ~b~Ibirth~N happened to be a ~r~Ipointer~N too, we'd use:
  496.  
  497.     ~b~Iptr->birth->month~N
  498. .w
  499. .WK3,60
  500.  MORAL???
  501. .W
  502.  
  503.     Use   ~b~Isam.birth ~N     if ~b~Isam~N is a structure.
  504.     Use   ~b~Isam->birth~N     if ~b~Isam~N is a ~r~Ipointer~N to a structure.    
  505. .WN
  506.  
  507.  
  508.  
  509. .T
  510.    That's all folks!   
  511. .K16,32
  512. au revoir!
  513.  
  514.  
  515. .q
  516.  
  517.